home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / amiga / opalvisn / lsidocs.lha / Source / Savers / Rendition.c next >
Encoding:
C/C++ Source or Header  |  1993-07-26  |  8.9 KB  |  353 lines

  1. /*  Rendition.c           by Martin Boyd 25-Apr-93.
  2.  *
  3.  *  An example file saver using the OpalVision LSI interface.
  4.  *
  5.  *  The rendition file format simply consists of a 1024 byte
  6.  * header (Described below) followed by 32 bit (RGBA) image data
  7.  * compressed using run-length encoding. Each run is encoded as
  8.  * 6 bytes:
  9.  *
  10.  *    Byte 0 - Red
  11.  *    Byte 1 - Green
  12.  *    Byte 2 - Blue
  13.  *    Byte 3 - Alpha
  14.  *    Byte 4 - Run length low byte
  15.  *    Byte 5 - Run length high byte
  16.  *
  17.  * NOTE: This saver only saves the 6RN format as described
  18.  *      above.
  19.  */
  20.  
  21. #include <proto/exec.h>
  22. #include <proto/dos.h>
  23. #include <opal/opallib.h>
  24. #include <opal/loadsave.h>
  25. #include <dos/dos.h>
  26. #include <dos/dosextens.h>
  27. #include <exec/memory.h>
  28. #include <exec/types.h>
  29. #include <exec/ports.h>
  30. #include <exec/nodes.h>
  31. #include <stdlib.h>
  32. #include <string.h>
  33.  
  34.  
  35. char Version[] = "\0$VER: Rendition.Saver 1.0 (25.04.93)";
  36.  
  37.     /* Rendition format information */
  38.  
  39. struct Tile
  40.     { long Ptr;
  41.       long Length;
  42.     };
  43.  
  44. struct RendHeader        /* 1024 byte header          */
  45.     { long    Magic;        /* H_MAGIC              */ 
  46.       SHORT    Version;    /* 2                  */
  47.       char    Label[128];    /* ASCII Desciption          */
  48.       char    Date[26];    /* Date of image creation      */
  49.       SHORT    Height;        /* Pixel height of image      */
  50.       SHORT    Width;        /* Pixel width of image          */
  51.       SHORT    TileHeight;    /* Pixel height of tile          */
  52.       SHORT    TileWidth;    /* Pixel width of tile          */
  53.       SHORT    Format;        /* See below              */
  54.       SHORT    Encoding;    /* See below              */
  55.       long    NumRuns;    /* Number of runs          */
  56.       SHORT    BlockSize;    /* 1024                  */
  57.       SHORT XOffset;    /* Horizontal offset          */
  58.       SHORT YOffset;    /* Vertical offset          */
  59.       long CMapLen;        /* Number of colour table entries */
  60.       long CMapPtr;        /* Pointer to ColourMap          */
  61.       char CMapName[64];    /* Colour Map filename          */
  62.       struct Tile Tile[64];    /* Tile pointer table          */
  63.       char UnSpec[258];    /* Unspecified (reserved)      */
  64.     };
  65.  
  66.  
  67. #define H_MAGIC        0xE880
  68. #define H_BLOCKSIZE    1024
  69. #define H_HEADERSIZE    1024
  70.  
  71.     /* Format types */
  72. #define H_CRGBAPIX    2    /* 4 bytes per pixel    */
  73. #define H_6RUNLH    11    /* 6 bytes per run    */
  74. #define H_2RUN        12    /* 2 bytes per run; colour map in seperate file */
  75. #define H_2RUNMAP    13    /* 2 bytes per run; colour map in image file */
  76. #define H_COLOURMAP    20    /* 4 bytes per entry    */
  77. #define H_MIPMAP    22    /* Mip map: header, map table and 4-byte pixels */
  78. #define H_ONEDRGBA8    23    /* 1D table of 4-byte pixels */
  79. #define H_ONEDBYTE    24    /* 1D table of bytes */
  80.  
  81.  
  82. extern struct DosLibrary *DOSBase;
  83. struct OpalBase *OpalBase;
  84. struct MsgPort *SavePort;
  85. int Width,Height;
  86. char *FileName;
  87. ULONG SaveFlags;
  88. struct RendHeader RendHeader;
  89.  
  90.  
  91. BOOL Do_Save (void);
  92.  
  93. char SaverName[] = "Rendition";
  94. char PortName[] = "Rendition_Saver";
  95.  
  96. char Comment[] = "Written by OpalVision Rendition Saver v1.0";
  97.  
  98.  
  99. void main (void)
  100. {
  101.    struct LSIMessage *LSIMesg;
  102.  
  103.     SavePort = CreatePort (PortName,0);
  104.     if (SavePort==NULL)
  105.         exit (10);
  106.     OpalBase = (struct OpalBase *)OpenLibrary ("opal.library",0);
  107.     if (OpalBase==NULL)
  108.         { DeletePort (SavePort);
  109.           exit (10);
  110.         }
  111.  
  112.  
  113.     if (!AddOVSaver (SaverName,SavePort,
  114.             OVSF_ALLOWIMAGE|OVSF_ALLOWALPHA|OVSF_NEEDFILENAME))
  115.         { DeletePort (SavePort);
  116.           CloseLibrary ((struct Library *)OpalBase);
  117.           exit (10);
  118.         }
  119.     CloseLibrary ((struct Library *)OpalBase);    /* library must be closed */
  120.     OpalBase = NULL;
  121.  
  122.     while (1)
  123.         { WaitPort (SavePort);
  124.           while (LSIMesg = (struct LSIMessage *)GetMsg (SavePort))
  125.             { switch (LSIMesg->lsi_Type)
  126.                 { case OVCMD_SAVEIMAGE:
  127.                     Width = LSIMesg->lsi_Width;
  128.                     Height = LSIMesg->lsi_Height;
  129.                     FileName = LSIMesg->lsi_FileName;
  130.                     SaveFlags = LSIMesg->lsi_Flags;
  131.                     ReplyMsg ((struct Message *)LSIMesg);
  132.                     Do_Save();
  133.                     break;
  134.                   case OVCMD_EXPUNGE:
  135.                     if (!OpalBase)
  136.                         OpalBase = (struct OpalBase *)OpenLibrary ("opal.library",0);
  137.                     RemOVSaver (SaverName);
  138.                     if (OpalBase)
  139.                         CloseLibrary ((struct Library *)OpalBase);
  140.                     DeletePort (SavePort);
  141.                     ReplyMsg ((struct Message *)LSIMesg);
  142.                     exit (0);
  143.                     break;
  144.                   case OVCMD_PARAMETERS:
  145.                     /* No parameters */
  146.                     break;
  147.                 }
  148.             }
  149.         }
  150. }
  151.  
  152.  
  153. /* I'm not sure if the format allows run length compression
  154.  * beyond the end of a line, so to be safe I end the compression
  155.  * at the end of each scan line.
  156.  */
  157.  
  158.  
  159. BOOL Do_Save (void)
  160. {
  161.    int x,y;
  162.    struct MsgPort *MasterPort;
  163.    struct LSIMessage LSIMesg;
  164.    BPTR File;
  165.    UBYTE *SrcBuff,*DestBuff;
  166.    register UBYTE *D,*R,*G,*B,*A,RData,GData,BData,AData;
  167.    long SBuffSize,DBuffSize,BuffRows,RowsLeft,Size,RunLength;
  168.    struct DateTime DT;
  169.  
  170.  
  171.         /* Get a handle on the Host port */
  172.     MasterPort = FindPort (OVSAVERPORT);
  173.     if (MasterPort==NULL) return (FALSE);
  174.  
  175.         /* Allocate buffers for compression */
  176.     BuffRows = 20;
  177.     SrcBuff = NULL;
  178.     DestBuff = NULL;
  179.     do
  180.         { SBuffSize = BuffRows * Width*4;
  181.           DBuffSize = BuffRows * Width*6;
  182.           SrcBuff = AllocMem (SBuffSize,MEMF_CLEAR);
  183.           if (SrcBuff!=NULL)
  184.             { DestBuff = AllocMem (DBuffSize,MEMF_CLEAR);
  185.               if (DestBuff==NULL)
  186.                 { FreeMem (SrcBuff,SBuffSize);
  187.                   SrcBuff=NULL;
  188.                 }
  189.             }
  190.           if (SrcBuff==NULL) BuffRows--;
  191.         } while ((SrcBuff==NULL) && (DestBuff==NULL) && (BuffRows>0));
  192.  
  193.     if (BuffRows==0)
  194.         { LSIMesg.lsi_Type = OVCMD_ERROR;
  195.           LSIMesg.lsi_Result = LSI_ERR_OUTOFMEM;
  196.           LSICmd (MasterPort,SavePort,&LSIMesg);
  197.           return (FALSE);
  198.         }
  199.  
  200.     memset (&LSIMesg,0,sizeof(struct LSIMessage));
  201.     LSIMesg.lsi_Node.mn_Node.ln_Type = NT_MESSAGE;
  202.     LSIMesg.lsi_Node.mn_ReplyPort = SavePort;
  203.     LSIMesg.lsi_Node.mn_Length = sizeof (struct LSIMessage);
  204.  
  205.     File = Open (FileName,MODE_NEWFILE);
  206.     if (File==NULL)
  207.         { FreeMem (SrcBuff,SBuffSize);
  208.           FreeMem (DestBuff,DBuffSize);
  209.           LSIMesg.lsi_Type = OVCMD_ERROR;
  210.           LSIMesg.lsi_Result = LSI_ERR_OPENFILE;
  211.           LSICmd (MasterPort,SavePort,&LSIMesg);
  212.           return (FALSE);
  213.         }
  214.  
  215.         /* Initialise File Header */
  216.     memset (&RendHeader,0,sizeof(struct RendHeader));
  217.     RendHeader.Magic = H_MAGIC;
  218.     RendHeader.Version = 2;
  219.     strcpy (RendHeader.Label,Comment);
  220.     if (DOSBase->dl_lib.lib_Version>=36)
  221.         { DateStamp (&DT.dat_Stamp);
  222.           DT.dat_Format = FORMAT_DOS;
  223.           DT.dat_Flags = 0;
  224.           DT.dat_StrDay = NULL;
  225.           DT.dat_StrDate = RendHeader.Date;
  226.           DT.dat_StrTime = &RendHeader.Date[10];
  227.           DateToStr (&DT);
  228.           RendHeader.Date[9] = ' ';
  229.         }
  230.     RendHeader.Width = Width;
  231.     RendHeader.Height = Height;
  232.     RendHeader.Format = H_6RUNLH;
  233.     Size = sizeof (struct RendHeader);
  234.  
  235.         /* Write the header */
  236.     if (Write (File,&RendHeader,Size)!=Size)
  237.         { FreeMem (SrcBuff,SBuffSize);
  238.           FreeMem (DestBuff,DBuffSize);
  239.           Close (File);
  240.           LSIMesg.lsi_Type = OVCMD_ERROR;
  241.           LSIMesg.lsi_Result = LSI_ERR_FILEWRITE;
  242.           LSICmd (MasterPort,SavePort,&LSIMesg);
  243.           return (FALSE);
  244.         }
  245.  
  246.         /* Compress and Write the body */
  247.     RowsLeft=0;
  248.     D = DestBuff;
  249.  
  250.     for (y=0; y<Height; y++)
  251.         { if (RowsLeft==0)
  252.             { if (y>0)
  253.                 { Size = D-DestBuff;
  254.                   if (Write (File,DestBuff,Size)!=Size)
  255.                     { FreeMem (SrcBuff,SBuffSize);
  256.                       FreeMem (DestBuff,DBuffSize);
  257.                       Close (File);
  258.                       LSIMesg.lsi_Type = OVCMD_ERROR;
  259.                       LSIMesg.lsi_Result = LSI_ERR_FILEWRITE;
  260.                       LSICmd (MasterPort,SavePort,&LSIMesg);
  261.                       return (FALSE);
  262.                     }
  263.                 }
  264.                 /* Get some image data (in RGB) */
  265.               D = DestBuff;
  266.               R = SrcBuff;
  267.               G = SrcBuff + BuffRows*Width;
  268.               B = SrcBuff + (2*BuffRows*Width);
  269.               A = SrcBuff + (3*BuffRows*Width);
  270.               LSIMesg.lsi_Width = Width;
  271.               LSIMesg.lsi_Height = BuffRows;
  272.               LSIMesg.lsi_X = 0;
  273.               LSIMesg.lsi_Y = y;
  274.               LSIMesg.lsi_Type = OVCMD_GETDATA;
  275.               LSIMesg.lsi_SubType = OVDF_RGB;
  276.               LSIMesg.lsi_Planes[0] = R;
  277.               LSIMesg.lsi_Planes[1] = G;
  278.               LSIMesg.lsi_Planes[2] = B;
  279.               LSICmd (MasterPort,SavePort,&LSIMesg);
  280.  
  281.                 /* If image has an Alpha chanel, get alpha
  282.                  * data, else set Alpha to 0xFF
  283.                  */
  284.  
  285.               if (SaveFlags & LSIF_ALPHA)
  286.                 { LSIMesg.lsi_SubType = OVDF_ALPHA;
  287.                   LSIMesg.lsi_Planes[0] = A;
  288.                   LSICmd (MasterPort,SavePort,&LSIMesg);
  289.                 }
  290.               else
  291.                 { for (x=BuffRows*Width; x>0; x--)
  292.                     *A++ = 0xFF;
  293.                   A = SrcBuff + (3*BuffRows*Width);
  294.                 }
  295.               RowsLeft = BuffRows;
  296.             }
  297.           RData = *R++;
  298.           GData = *G++;
  299.           BData = *B++;
  300.           AData = *A++;
  301.           RunLength = 1;
  302.           for (x=1; x<Width; x++)
  303.             { if ((*R==RData) && (*G==GData) && (*B==BData) &&
  304.                 (*A==AData))
  305.                 { RunLength++;
  306.                   R++; G++; B++; A++;
  307.                 }
  308.               else
  309.                 { *D++ = RData;
  310.                   *D++ = GData;
  311.                   *D++ = BData;
  312.                   *D++ = AData;
  313.                   *D++ = RunLength & 0xFF;
  314.                   *D++ = (RunLength>>8) & 0xFF;
  315.                   RData = *R++;
  316.                   GData = *G++;
  317.                   BData = *B++;
  318.                   AData = *A++;
  319.                   RunLength = 1;
  320.                 }
  321.             }
  322.           *D++ = RData;
  323.           *D++ = GData;
  324.           *D++ = BData;
  325.           *D++ = AData;
  326.           *D++ = RunLength & 0xFF;
  327.           *D++ = (RunLength>>8) & 0xFF;
  328.  
  329.           if ((y & 0xF)==0)
  330.             { LSIMesg.lsi_Type = OVCMD_PERCENTAGE;
  331.               LSIMesg.lsi_Address = "Rend ";
  332.               LSIMesg.lsi_Result = (y*100)/Height;
  333.               LSICmd (MasterPort,SavePort,&LSIMesg);
  334.             }
  335.           RowsLeft--;
  336.         }
  337.  
  338.         /* Write out whatever's left */
  339.     Size = D-DestBuff;
  340.     if (Size>0)
  341.         Write (File,DestBuff,Size);
  342.  
  343.     LSIMesg.lsi_Type = OVCMD_DONE;
  344.     LSICmd (MasterPort,SavePort,&LSIMesg);
  345.     Close (File);
  346.     FreeMem (SrcBuff,SBuffSize);
  347.     FreeMem (DestBuff,DBuffSize);
  348.     return (TRUE);
  349. }
  350.  
  351.  
  352.  
  353.